/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-07-07 09:42:14
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-07-07 14:27:21
 * @FilePath: /lesson/lesson_net/blog_http/SocketMain.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;

int main()
{
    // 1、创建
    int listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sockfd < 0)
    {
        cerr << "create failed!" << endl;
        exit(-1);
    }
    // 2、绑定
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));

    local.sin_family = AF_INET;
    local.sin_port = htons(8888);
    local.sin_addr.s_addr = INADDR_ANY;

    if (bind(listen_sockfd, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        cerr << "bind failed!" << endl;
        exit(-2);
    }
    // 3、监听
    if (listen(listen_sockfd, 5) < 0)
    {
        cerr << "listen failed" << endl;
        exit(-3);
    }

    // 4、接收accept
    // 在接受之前，一定要再创建一个sockaddr_in结构体，只需要memset清空操作即可，目的：用于存储传过来的客户端网络信息！！！
    struct sockaddr_in peer;
    memset(&peer, 0, sizeof(peer));
    socklen_t len = sizeof(peer);

    while (true)
    {
        int sockfd = accept(listen_sockfd, (struct sockaddr *)&peer, &len);
        if (sockfd < 0)
        {
            cerr << "accept failed" << endl;
            continue;
        }
        // 5、创建子进程让其处理请求（多线程版）
        if (fork() == 0) // 子进程代码
        {
            close(listen_sockfd);
            if (fork() > 0) // 父进程代码
                exit(0);

            // 孙子进程:打印http请求
            char buffer[1024];
            recv(sockfd, buffer, sizeof(buffer), 0);
            cout << "--------------------------http request begin--------------------------" << endl;
            cout << buffer << endl;
            cout << "---------------------------http request end---------------------------" << endl;

#define PAGE "index.html" // 网站首页
            // 读取index.html文件
            ifstream in(PAGE);

            if (in.is_open())
            {
                in.seekg(0, in.end);
                int len = in.tellg();
                in.seekg(0, in.beg);
                char *file = new char[len];
                in.read(file, len);
                in.close();

                // 构建HTTP响应
                string status_line = "http/1.1 200 OK\n";                                // 状态行
                string response_header = "Content-Length:" + to_string(len) + "\n";      // 响应报头
                string blank = "\n";                                                     // 空行
                string response_text = file;                                             // 正文
                string response = status_line + response_header + blank + response_text; // 响应报文

                send(sockfd, response.c_str(), response.size(), 0); // 响应http请求
                delete[] file;
            }
            // 爷爷进程
            close(sockfd);
            waitpid(-1, nullptr, 0); // 等待爸爸进程
        }

        return 0;
    }
}